const path = require('path');
const fs = require('fs').promises;
const xlsx = require('xlsx');
const QRCode = require('qrcode');
const { sequelize, Certificate, Field, ImportExportRecord } = require('../models');
const logger = require('../utils/logger');
const { Op } = require('sequelize');
const glob = require('glob');
const redis = require('../config/redis');

// 文件格式的 MIME 类型映射
const MIME_TYPES = {
  xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  xls: 'application/vnd.ms-excel',
  csv: 'text/csv'
};

// 获取文件扩展名
const getFileExtension = (filename) => {
  return filename.split('.').pop().toLowerCase();
};

// 获取 MIME 类型
const getMimeType = (filename) => {
  const ext = getFileExtension(filename);
  return MIME_TYPES[ext] || 'application/octet-stream';
};

// 获取证书编号
const getCertNumber = (fields) => {
  const certNumberField = fields.find(f => f.field_name === 'cert_number');
  return certNumberField ? certNumberField.description : '';
};

// 生成二维码
const generateQRCode = async (certificate, transaction = null) => {
  try {
    const qrcodesDir = path.join(process.cwd(), 'uploads', 'qrcodes');
    await fs.mkdir(qrcodesDir, { recursive: true });

    // 确保 fields 是数组
    const fields = Array.isArray(certificate.fields) ? 
      certificate.fields : 
      JSON.parse(certificate.fields);

    // 使用证书编号作为文件名
    const certNumber = getCertNumber(fields);
    if (!certNumber) {
      throw new Error('未找到证书编号');
    }

    const qrCodeFileName = `${certNumber}.png`;
    const qrCodePath = path.join(qrcodesDir, qrCodeFileName);
    
    // 生成二维码，使用证书编号作为外链后缀
    const baseUrl = process.env.BASE_URL || 'http://localhost:3800';
    const certificateUrl = `${baseUrl}/view/${certNumber}`;
    
    logger.info('生成二维码:', {
      certNumber,
      qrCodePath,
      certificateUrl
    });

    // 生成二维码
    await QRCode.toFile(qrCodePath, certificateUrl, {
      width: 300,
      margin: 2,
      color: {
        dark: '#000000',
        light: '#ffffff'
      }
    });
    
    // 更新证书的二维码路径
    const updateOptions = transaction ? { transaction } : {};
    await certificate.update({ qr_code_path: `qrcodes/${qrCodeFileName}` }, updateOptions);
    
    return qrCodeFileName;
  } catch (error) {
    logger.error('生成二维码失败:', error);
    throw error;
  }
};

// 生成序号
const generateSequenceNumber = async (transaction) => {
  // 获取最大序号
  const lastCert = await Certificate.findOne({
    order: [['sequence_number', 'DESC']],
    transaction
  });

  // 如果存在证书，获取最后一个序号并加1，否则从1开始
  let sequence = 1;
  if (lastCert && lastCert.sequence_number) {
    sequence = parseInt(lastCert.sequence_number) + 1;
  }

  // 返回4位数字格式：0001
  return String(sequence).padStart(4, '0');
};

// 检查数据库连接
const checkDatabaseConnection = async () => {
  try {
    await sequelize.authenticate();
    return true;
  } catch (error) {
    logger.error('数据库连接检查失败:', error);
    return false;
  }
};

// 缓存键前缀
const CACHE_KEY = {
  RECORD_LIST: 'record:list:',
  AVAILABLE_FIELDS: 'available:fields'
};

// 缓存时间(秒)
const CACHE_TTL = {
  RECORD_LIST: 60 * 5, // 5分钟
  AVAILABLE_FIELDS: 60 * 60 * 24 // 24小时
};

// 获取可选字段列表
exports.getAvailableFields = async (req, res) => {
  try {
    // 尝试从缓存获取
    const cachedData = await redis.get(CACHE_KEY.AVAILABLE_FIELDS);
    if (cachedData) {
      logger.info('从缓存获取可选字段列表');
      return res.json(JSON.parse(cachedData));
    }

    // 获取所有字段
    const fields = await Field.findAll({
      attributes: ['id', 'name', 'field_name', 'required', 'description'],
      order: [['id', 'ASC']],
      raw: true
    });

    if (!fields.length) {
      return res.status(500).json({ message: '未找到字段配置' });
    }

    // 分离证书编号字段和其他字段
    const certNumberField = fields.find(f => f.field_name === 'cert_number');
    const otherFields = fields.filter(f => f.field_name !== 'cert_number');

    const result = {
      cert_number: certNumberField,
      available_fields: otherFields,
      max_selectable: 11,
      total_max: 12
    };

    // 设置缓存
    await redis.set(CACHE_KEY.AVAILABLE_FIELDS, JSON.stringify(result), 'EX', CACHE_TTL.AVAILABLE_FIELDS);
    logger.info('可选字段列表已缓存');

    res.json(result);
  } catch (error) {
    logger.error('获取可选字段失败:', error);
    res.status(500).json({ message: '获取字段列表失败' });
  }
};

// 下载导入模板
exports.getTemplate = async (req, res) => {
  try {
    logger.info('开始处理下载模板请求:', {
      body: req.body,
      headers: req.headers
    })

    const { fields } = req.body;
    if (!fields || !Array.isArray(fields)) {
      logger.warn('字段参数无效:', fields)
      return res.status(400).json({ message: '请选择要导出的字段' });
    }

    // 获取字段信息
    const fieldList = await Field.findAll({
      where: {
        field_name: fields
      },
      attributes: ['name', 'field_name', 'required'],
      order: [['name', 'ASC']]
    });

    logger.info('查询到的字段:', fieldList.map(f => ({
      name: f.name,
      field_name: f.field_name
    })))

    if (!fieldList.length) {
      logger.warn('未找到选中的字段')
      return res.status(400).json({ message: '未找到选中的字段' });
    }

    // 创建工作簿
    const workbook = xlsx.utils.book_new();
    const worksheet = xlsx.utils.aoa_to_sheet([
      // 表头：字段名称
      fieldList.map(field => field.name),
      // 示例数据
      fieldList.map(field => {
        if (field.field_name === 'cert_number') {
          return 'XK21-015（示例）'
        }
        return field.required ? '必填项' : '选填项'
      })
    ]);

    // 设置列宽
    const colWidths = fieldList.map(field => ({ wch: Math.max(field.name.length * 2, 15) }));
    worksheet['!cols'] = colWidths;

    // 添加工作表
    xlsx.utils.book_append_sheet(workbook, worksheet, '导入模板');

    // 生成 buffer
    const buffer = xlsx.write(workbook, { type: 'buffer', bookType: 'xlsx' });

    // 生成文件名
    const filename = `import_template_${new Date().toISOString().slice(0,10)}.xlsx`;

    logger.info('准备发送文件:', {
      filename,
      size: buffer.length,
      type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
    })

    // 设置响应头
    res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
    res.setHeader('Content-Disposition', `attachment; filename="${encodeURIComponent(filename)}"`);
    res.setHeader('Access-Control-Expose-Headers', 'Content-Disposition');
    res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
    res.setHeader('Pragma', 'no-cache');
    res.setHeader('Expires', '0');

    // 发送文件
    res.send(buffer);
    logger.info('文件发送成功')
  } catch (error) {
    logger.error('下载模板失败:', error);
    res.status(500).json({ message: '下载模板失败: ' + error.message });
  }
};

// 预览导入数据
exports.previewImport = async (req, res) => {
  try {
    if (!req.file) {
      return res.status(400).json({ message: '请选择文件' });
    }

    logger.info('开始处理上传文件:', {
      originalName: req.file.originalname,
      size: req.file.size,
      path: req.file.path
    });

    // 直接读取上传的文件
    const workbook = xlsx.read(req.file.buffer, { type: 'buffer' });
    const sheetName = workbook.SheetNames[0];
    const worksheet = workbook.Sheets[sheetName];
    
    logger.info('Excel文件基本信息:', {
      sheets: workbook.SheetNames,
      firstSheet: sheetName,
      range: worksheet['!ref']
    });

    // 获取表头（字段名）
    const range = xlsx.utils.decode_range(worksheet['!ref']);
    const headers = [];
    const headerMap = new Map();
    
    // 检查字段名
    for (let C = range.s.c; C <= range.e.c; ++C) {
      const cell = worksheet[xlsx.utils.encode_cell({ r: 0, c: C })];
      const header = cell ? cell.v : undefined;
      
      if (!header) continue;

      // 检查字段名长度
      const isChinese = /[\u4e00-\u9fa5]/.test(header);
      if (isChinese && header.length > 10) {
        return res.status(400).json({ 
          message: `导入失败：字段名"${header}"超过10个中文字符的限制` 
        });
      }
      if (!isChinese && header.length > 20) {
        return res.status(400).json({ 
          message: `导入失败：字段名"${header}"超过20个字符的限制` 
        });
      }
      
      // 检查是否有重复字段名
      if (headerMap.has(header)) {
        return res.status(400).json({ 
          message: '导入失败：文件中包含多个相同字段名的列' 
        });
      }
      headerMap.set(header, C);
      headers.push(header);
    }

    // 检查是否包含证书编号字段
    if (!headers.includes('证书编号')) {
      return res.status(400).json({ 
        message: '导入失败：导入文件缺少证书编号字段' 
      });
    }

    // 转换数据并验证
    const data = xlsx.utils.sheet_to_json(worksheet);
    logger.info('Excel原始数据:', data);

    // 检查数据行数是否超过限制
    if (data.length > 100) {
      return res.status(400).json({ 
        message: '导入失败：单次最多允许导入100行数据' 
      });
    }

    const previewData = [];
    const errors = [];
    const warnings = [];
    let validCount = 0;

    // 获取所有已存在的字段
    const existingFields = await Field.findAll({
      attributes: ['name', 'field_name'],
      raw: true
    });

    // 获取所有已存在的字段名和字段标识
    const existingFieldNames = existingFields.map(f => f.name);
    const existingFieldIdentifiers = existingFields.map(f => f.field_name);
    logger.info('已存在的字段名:', existingFieldNames);
    logger.info('已存在的字段标识:', existingFieldIdentifiers);

    for (let i = 0; i < data.length; i++) {
      const row = data[i];
      const rowNum = i + 2; // Excel行号从1开始，且跳过表头
      const rowWarnings = []; // 存储当前行的警告
      
      logger.info(`处理第${rowNum}行数据:`, row);
      
      // 检查证书编号并标记错误
      if (!row['证书编号']) {
        errors.push(`第${rowNum}行缺少证书编号`);
        row.error = true;
        logger.info(`第${rowNum}行缺少证书编号`);
      }

      // 检查有效字段数量（排除空值和内部属性）
      const validFields = Object.entries(row).filter(([fieldName, value]) => {
        // 排除内部属性
        if (['error', 'warning', 'warnings'].includes(fieldName)) {
          return false;
        }
        // 排除空值和undefined
        const isEmpty = value === null || value === undefined || value === '';
        // 记录日志
        logger.info(`第${rowNum}行字段 ${fieldName} 的值:`, value, isEmpty ? '(空值)' : '(有值)');
        return !isEmpty;
      });
      
      // 检查字段数量
      if (validFields.length > 12) {
        const warning = `第${rowNum}行证书字段超过最大（包含证书编号）12`;
        rowWarnings.push(warning);
        warnings.push(warning);
        row.warning = true;
      }

      // 检查是否只有证书编号
      if (validFields.length === 1 && row['证书编号']) {
        const warning = `第${rowNum}行只有证书编号，没有其他值`;
        rowWarnings.push(warning);
        warnings.push(warning);
        row.warning = true;
      }

      // 检查是否有新字段
      const newFields = validFields.filter(([fieldName]) => {
        // 如果是证书编号，不算新字段
        if (fieldName === '证书编号') return false;
        
        // 如果字段名为空，不算新字段
        if (!fieldName.trim()) return false;
        
        // 如果字段名或字段标识已存在，不算新字段
        if (existingFieldNames.includes(fieldName) || existingFieldIdentifiers.includes(fieldName)) {
          return false;
        }
        
        // 记录日志
        logger.info(`检查字段 ${fieldName} 是否为新字段:`, {
          isInNames: existingFieldNames.includes(fieldName),
          isInIdentifiers: existingFieldIdentifiers.includes(fieldName)
        });
        
        return true;
      });

      if (newFields.length > 0) {
        logger.info(`第${rowNum}行发现新字段:`, newFields.map(([fieldName]) => fieldName));
        const warning = `第${rowNum}行出现了新的字段"${newFields[0][0]}"`;
        rowWarnings.push(warning);
        warnings.push(warning);
        row.warning = true;
      }

      // 检查是否包含特殊字符
      for (const [_, value] of validFields) {
        if (typeof value === 'string' && /[<>{}[\]\\\/]/.test(value)) {
          const warning = `第${rowNum}行包含特殊字符，将自动转换格式`;
          rowWarnings.push(warning);
          warnings.push(warning);
          row.warning = true;
          break;
        }
      }

      // 检查证书编号是否已存在
      if (row['证书编号']) {
        const existingCert = await Certificate.findOne({
          where: sequelize.literal(`JSON_CONTAINS(fields, '{"field_name": "cert_number", "description": "${row['证书编号']}"}')`)
        });

        if (existingCert) {
          errors.push(`第${rowNum}行证书编号已存在`);
          row.error = true;
        }
      }

      // 将当前行的警告添加到行数据中
      row.warnings = rowWarnings;
      
      validCount++;
      previewData.push(row);
      logger.info(`第${rowNum}行处理完成，警告:`, rowWarnings);
    }

    logger.info('预览数据处理完成，总行数:', previewData.length);

    // 获取当前最大序号
    const lastCert = await Certificate.findOne({
      order: [['sequence_number', 'DESC']]
    });

    // 如果存在证书，获取最后一个序号，否则从0开始
    const maxSequenceNumber = lastCert ? parseInt(lastCert.sequence_number) : 0;
    
    logger.info('当前最大序号:', maxSequenceNumber);

    res.json({
      code: 200,
      message: '预览成功',
      data: {
        headers,
        previewData,
        total: data.length,
        valid: validCount,
        errors,
        warnings,
        tempFilePath: req.file.path,  // 这个值现在会是 undefined, 后续需要处理
        maxSequenceNumber
      }
    });
  } catch (error) {
    logger.error('预览导入数据失败:', {
      error: error.message,
      stack: error.stack,
      file: req.file ? {
        originalName: req.file.originalname,
        path: req.file.path,
        size: req.file.size
      } : null
    });

    res.status(400).json({
      code: 400,
      message: error.message || '预览失败',
      data: null
    });
  }
};

// 取消导入
exports.cancelImport = async (req, res) => {
  try {
    const { tempFilePath } = req.body;
    if (!tempFilePath) {
      return res.status(400).json({ message: '未找到要取消的文件' });
    }

    logger.info('准备取消导入:', tempFilePath);

    try {
      // 检查文件是否存在
      await fs.access(tempFilePath);
      // 删除文件
      await fs.unlink(tempFilePath);
      logger.info('已删除临时文件:', tempFilePath);
    } catch (error) {
      logger.warn('清理临时文件失败或文件不存在:', {
        path: tempFilePath,
        error: error.message
      });
    }

    res.json({ 
      code: 200,
      message: '已取消导入' 
    });
  } catch (error) {
    logger.error('取消导入失败:', error);
    res.status(500).json({ 
      code: 500,
      message: '取消导入失败' 
    });
  }
};

// 确认导入
exports.confirmImport = async (req, res) => {
  let transaction = null;
  
  try {
    // 记录开始时间和完整请求数据
    const startTime = new Date();
    logger.info('确认导入 - 完整请求数据:', {
      body: {
        tempFilePath: req.body.tempFilePath,
        dataLength: req.body.data?.length,
        dataType: typeof req.body.data,
        isDataArray: Array.isArray(req.body.data),
        firstRow: req.body.data?.[0]
      },
      headers: req.headers,
      method: req.method
    });
    
    transaction = await sequelize.transaction();
    logger.info('确认导入 - 事务状态:', {
      isActive: transaction.finished === 'undefined',
      id: transaction.id
    });
    
    // 从请求中获取文件和数据
    const file = req.file;
    const { data } = req.body;

    if (!file) {
      logger.error('确认导入 - 未找到文件');
      return res.status(400).json({ message: '未找到要导入的文件' });
    }

    let importData;
    
    try {
      // 尝试解析数据
      if (typeof data === 'string') {
        importData = JSON.parse(data);
      } else {
        importData = data;
      }
      
      // 验证数据格式
      if (!importData || !Array.isArray(importData)) {
        logger.error('确认导入 - 数据格式无效:', {
          hasData: !!importData,
          type: typeof importData,
          isArray: Array.isArray(importData)
        });
        return res.status(400).json({ message: '无效的导入数据' });
      }
      
      logger.info('确认导入 - 数据解析成功:', {
        length: importData.length,
        firstRow: importData[0]
      });
    } catch (error) {
      logger.error('确认导入 - 数据解析失败:', {
        error: error.message,
        data: data
      });
      return res.status(400).json({ message: '数据解析失败' });
    }

    // 创建导入记录
    const record = await ImportExportRecord.create({
      type: '导入',
      file_name: file.originalname, // 使用原始文件名
      status: '进行中',
      file_size: file.size,
      created_at: startTime
    }, { transaction });
    logger.info('确认导入 - 记录创建成功:', {
      recordId: record.id,
      fileName: record.file_name,
      fileSize: record.file_size,
      status: record.status
    });

    // 获取现有字段
    const existingFields = await Field.findAll({
      attributes: ['id', 'name', 'field_name'],
      raw: true
    });
    logger.info('确认导入 - 现有字段:', {
      count: existingFields.length,
      fields: existingFields.map(f => ({
        id: f.id,
        name: f.name,
        field_name: f.field_name
      }))
    });

    // 处理新字段前的准备
    logger.info('确认导入 - 开始处理新字段:', {
      dataLength: importData.length,
      firstRowHeaders: Object.keys(importData[0])
    });

    // 处理新字段
    const fieldNameMap = new Map();
    for (const row of importData) {
      for (const header of Object.keys(row)) {
        // 排除特殊字段
        if (header === '证书编号' || header === 'sequence_number') continue;
        
        if (!fieldNameMap.has(header)) {
          const existingField = existingFields.find(f => f.name === header);
          logger.info('确认导入 - 字段处理:', {
            header,
            isExisting: !!existingField,
            existingFieldName: existingField?.field_name,
            value: row[header]
          });
          
          if (!existingField) {
            // 使用事务锁查询最大ID
            const [result] = await sequelize.query(
              'SELECT MAX(id) as maxId FROM fields FOR UPDATE',
              { transaction }
            );
            const maxId = result[0].maxId || 0;
            const nextId = maxId < 1 ? 2 : maxId + 1;
            
            logger.info('确认导入 - 准备创建新字段:', {
              header,
              maxId,
              nextId,
              field_name: header,
              transactionId: transaction.id
            });
            
            try {
              // 生成唯一的field_name
              const timestamp = Date.now();
              const fieldName = `field_${timestamp}`;
              
              // 创建新字段
              const newField = await Field.create({
                id: nextId,
                name: header,  // 使用Excel中的列名作为显示名称
                field_name: fieldName,  // 使用生成的唯一标识
                description: `从导入创建的字段：${header}`,
                required: false
              }, { transaction });

              logger.info('确认导入 - 新字段创建成功:', {
                id: newField.id,
                name: newField.name,
                field_name: newField.field_name,
                transactionId: transaction.id
              });

              fieldNameMap.set(header, fieldName);  // 使用生成的field_name
            } catch (fieldError) {
              logger.error('确认导入 - 创建新字段失败:', {
                header,
                error: fieldError.message,
                stack: fieldError.stack,
                transactionId: transaction.id
              });
              throw fieldError;
            }
          } else {
            fieldNameMap.set(header, existingField.field_name);
          }
        }
      }
    }

    logger.info('确认导入 - 字段映射完成:', {
      size: fieldNameMap.size,
      mappings: Array.from(fieldNameMap.entries()),
      transactionId: transaction.id
    });

    // 移动到正式导入目录
    const importsDir = path.join(process.cwd(), 'uploads', 'imports');
    await fs.mkdir(importsDir, { recursive: true });
    logger.info('确认导入 - 导入目录已创建:', {
      path: importsDir,
      isAbsolute: path.isAbsolute(importsDir)
    });

    // 使用 Buffer 处理文件名编码
    const originalName = file.originalname;
    const importFileName = `import_${Date.now()}_${originalName}`;
    const importFilePath = path.join(importsDir, importFileName);
    logger.info('确认导入 - 准备写入文件:', {
      to: importFilePath,
      fileName: importFileName,
      originalName
    });

    try {
      // 将内存中的文件写入磁盘
      await fs.writeFile(importFilePath, file.buffer);
      logger.info('确认导入 - 文件写入成功:', {
        newPath: importFilePath
      });
      
      // 验证写入后的文件
      const movedStat = await fs.stat(importFilePath);
      logger.info('确认导入 - 写入后文件状态:', {
        exists: true,
        size: movedStat.size,
        isFile: movedStat.isFile(),
        permissions: movedStat.mode
      });
      
      // 设置文件路径
      const relativePath = path.join('uploads', 'imports', importFileName);

      // 更新记录的file_name为新的文件名
      await record.update({
        file_name: importFileName,
        file_path: relativePath
      }, { transaction });
      
      logger.info('确认导入 - 记录更新成功:', {
        recordId: record.id,
        fileName: importFileName,
        filePath: relativePath
      });

      // 处理每一行数据
      const results = {
        total: importData.length,
        success: 0,
        skipped: 0,
        errors: []
      };

      // 处理每一行数据
      for (let i = 0; i < importData.length; i++) {
        const row = importData[i];
        const rowNum = i + 2;

        if (!row['证书编号']) {
          results.errors.push(`第${rowNum}行缺少证书编号`);
          results.skipped++;
          continue;
        }

        // 检查有效字段数量（排除空值）
        const validFields = Object.entries(row).filter(([_, value]) => 
          value !== null && value !== undefined && value !== ''
        );
        
        if (validFields.length > 12) {
          results.errors.push(`第${rowNum}行证书字段超过最大（包含证书编号）12`);
          results.skipped++;
          continue;
        }

        const existingCert = await Certificate.findOne({
          where: sequelize.literal(`JSON_CONTAINS(fields, '{"field_name": "cert_number", "description": "${row['证书编号']}"}')`)
        }, { transaction });

        if (existingCert) {
          results.errors.push(`第${rowNum}行证书编号已存在`);
          results.skipped++;
          continue;
        }

        // 生成序号
        const sequence_number = await generateSequenceNumber(transaction);

        // 转换数据格式（只保留非空值）
        const fields = [];

        // 添加证书编号字段
        fields.push({
          field_name: 'cert_number',
          name: '证书编号',
          description: row['证书编号']
        });

        // 添加其他字段
        for (const [header, value] of Object.entries(row)) {
          if (header === '证书编号') continue;
          if (value === null || value === undefined || value === '') continue;
          
          const fieldName = fieldNameMap.get(header);
          if (fieldName) {
            fields.push({
              field_name: fieldName,
              name: header,
              description: value
            });
          }
        }

        // 创建证书，sequence_number作为模型属性
        const certificate = await Certificate.create({
          sequence_number,
          fields
        }, { transaction });
        
        // 立即生成二维码
        try {
          logger.info(`正在为证书 ${certificate.id} 生成二维码`);
          await generateQRCode(certificate, transaction);
          logger.info(`证书 ${certificate.id} 的二维码生成成功`);
        } catch (error) {
          logger.error(`生成证书 ${certificate.id} 的二维码失败:`, error);
        }
        
        results.success++;
      }

      // 确定最终状态
      let status, message;
      if (results.success === 0) {
        status = '失败';
        if (results.total === results.skipped && results.errors.every(e => e.includes('证书编号已存在'))) {
          message = '导入失败：所有证书编号都已存在';
        } else {
          message = '导入失败：' + results.errors[0];
        }
      } else if (results.skipped > 0) {
        status = '部分成功';
        message = `导入部分成功：成功${results.success}条，失败${results.skipped}条`;
      } else {
        status = '成功';
        message = `导入成功${results.success}条新证书`;
      }

      // 计算耗时
      const duration = Math.round((Date.now() - startTime.getTime()) / 1000);

      // 更新记录状态（只更新一次）
      await record.update({
        status,
        file_path: relativePath,
        total_count: results.total,
        success_count: results.success,
        fail_count: results.skipped,
        error_message: results.errors.join('\n'),
        duration
      }, { transaction });

      await transaction.commit();
      transaction = null;
      logger.info('[IMPORT_END] 事务已提交');

      logger.info('准备清除证书列表缓存...');
      // 清除证书列表缓存
      try {
        const redis = require('../config/redis');
        const keys = await redis.keys('cert:list:*');
        if (keys.length > 0) {
          await redis.del(keys);
          logger.info(`成功清除了 ${keys.length} 个证书缓存: ${keys.join(', ')}`);
        } else {
          logger.info('没有找到需要清除的证书缓存');
        }
      } catch (cacheError) {
        logger.error('清除证书缓存失败:', cacheError);
      }
      logger.info('缓存清除操作完成');

      res.json({
        code: 200,
        message: status === '成功' ? '导入成功' : message,
        data: {
          total: results.total,
          success: results.success,
          skipped: results.skipped,
          errors: results.errors
        }
      });
      
    } catch (error) {
      logger.error('确认导入 - 移动文件失败:', {
        error: error.message,
        code: error.code,
        stack: error.stack,
        tempFilePath,
        importFilePath,
        transactionId: transaction.id
      });
      throw new Error('移动导入文件失败');
    }
  } catch (error) {
    logger.error('导入失败:', error);
    if (transaction) {
      await transaction.rollback();
    }
    res.status(400).json({ 
      code: 400,
      message: '导入失败: ' + error.message 
    });
  }
};

// 创建导出任务
exports.createExport = async (req, res) => {
  let transaction = null;
  let tempFilePath = null;
  
  try {
    // 记录开始时间
    const startTime = new Date();

    // 检查数据库连接
    const isConnected = await checkDatabaseConnection();
    if (!isConnected) {
      throw new Error('数据库连接失败，请稍后重试');
    }

    // 从 query 中获取参数
    let fields = [];
    try {
      if (req.query.fields) {
        // 记录原始参数
        logger.info('原始字段参数:', {
          raw: req.query.fields,
          type: typeof req.query.fields
        });

        // 解析字段参数
        try {
          const parsed = JSON.parse(req.query.fields);
          fields = Array.isArray(parsed) ? parsed : [];
          
          // 记录解析结果
          logger.info('解析后的字段:', {
            fields,
            length: fields.length
          });
        } catch (e) {
          logger.error('字段参数解析失败:', e);
          fields = [];
        }
      }
    } catch (parseError) {
      logger.error('字段参数处理失败:', {
        error: parseError.message,
        originalFields: req.query.fields
      });
      fields = [];
    }

    const { format, status, start_date, end_date, filename } = req.query;

    logger.info('处理后的导出参数:', {
      fields,
      format,
      status,
      start_date,
      end_date,
      filename
    });

    // 验证字段参数
    if (fields.length > 0 && !fields.every(field => typeof field === 'string' && field.startsWith('field_'))) {
      logger.error('字段格式不正确:', fields);
      return res.status(400).json({ message: '字段格式不正确' });
    }

    // 创建事务
    try {
      transaction = await sequelize.transaction();
      logger.info('事务创建成功');
    } catch (transactionError) {
      logger.error('事务创建失败:', transactionError);
      throw new Error('事务创建失败，请稍后重试');
    }

    // 生成文件名
    const currentFormat = format && format.toLowerCase() === 'csv' ? 'csv' : 'xlsx';
    const dateStr = new Date().toISOString().slice(0,10).replace(/-/g,'');
    const timeStr = new Date().toTimeString().slice(0,8).replace(/:/g,'');
    
    // 如果提供了filename，去掉其扩展名
    const baseFileName = filename ? path.parse(filename).name : `export_${dateStr}_${timeStr}`;
    const exportFileName = `${baseFileName}.${currentFormat}`;
    
    // 创建导出记录
    const record = await ImportExportRecord.create({
      type: '导出',
      file_name: exportFileName,
      status: '进行中',
      created_at: startTime
    }, { transaction });

    // 获取字段映射
    const fieldMapping = fields.length > 0 ? await Field.findAll({
      where: {
        field_name: {
          [Op.and]: [
            { [Op.in]: fields },
            { [Op.ne]: 'cert_number' }
          ]
        }
      },
      attributes: ['id', 'name', 'field_name'],
      raw: true,
      transaction
    }) : await Field.findAll({
      where: {
        field_name: {
          [Op.ne]: 'cert_number'
        }
      },
      attributes: ['id', 'name', 'field_name'],
      raw: true,
      transaction
    });

    // 添加详细日志
    logger.info('筛选字段信息:', {
      requestedFields: fields,
      mappedFields: fieldMapping.map(f => ({
        name: f.name,
        field_name: f.field_name
      }))
    });

    if (fields.length > 0 && !fieldMapping.length) {
      throw new Error('未找到选中的字段');
    }

    // 构建查询条件
    const where = {};
    if (status) {
      where.status = status === 'active' ? '启用中' : '停止中';
    }

    // 处理日期范围
    try {
      if (start_date && end_date) {
        const startDateTime = new Date(start_date);
        const endDateTime = new Date(end_date);
        
        if (isNaN(startDateTime.getTime()) || isNaN(endDateTime.getTime())) {
          throw new Error('日期格式不正确');
        }

        where.created_at = {
          [Op.between]: [startDateTime, endDateTime]
        };
      }
    } catch (dateError) {
      logger.error('日期处理错误:', dateError);
      throw new Error('日期格式不正确: ' + dateError.message);
    }

    logger.info('查询条件:', where);

    // 查询证书数据
    let certificates;
    if (fields.length > 0) {
      // 构建查询条件
      const whereCondition = {
        ...where,
        fields: {
          [Op.and]: fieldMapping.map(field => 
            sequelize.literal(`JSON_CONTAINS(fields, '{"field_name": "${field.field_name}"}')`)
          )
        }
      };
      
      // 记录实际的查询条件
      logger.info('导出查询条件:', {
        where: whereCondition,
        mappedFields: fieldMapping.map(f => f.field_name),
        sql: Certificate.queryGenerator.selectQuery('certificates', {
          where: whereCondition,
          attributes: ['sequence_number', 'fields', 'status', 'created_at']
        })
      });

      certificates = await Certificate.findAll({
        where: whereCondition,
        attributes: ['sequence_number', 'fields', 'status', 'created_at'],
        raw: true,
        transaction
      });

      // 添加日志查看证书数据结构
      logger.info('证书数据示例:', {
        total: certificates.length,
        firstCertificate: certificates[0] ? {
          sequence_number: certificates[0].sequence_number,
          fields: certificates[0].fields,
          status: certificates[0].status
        } : null
      });
    } else {
      certificates = await Certificate.findAll({
        where,
        attributes: ['sequence_number', 'fields', 'status', 'created_at'],
        raw: true,
        transaction
      });
    }

    logger.info(`查询到 ${certificates.length} 条证书数据`);

    if (certificates.length === 0) {
      throw new Error('未找到符合条件的数据');
    }

    // 获取所有字段映射（用于导出）
    const allFieldMapping = await Field.findAll({
      where: {
        field_name: {
          [Op.ne]: 'cert_number'  // 排除证书编号字段
        }
      },
      attributes: ['id', 'name', 'field_name'],
      raw: true,
      transaction
    });

    // 转换字段名称
    const exportData = certificates.map(cert => {
      const row = {};
      // 从fields中获取证书编号
      if (cert.fields && Array.isArray(cert.fields)) {
        const certNumberField = cert.fields.find(field => field.field_name === 'cert_number');
        row['证书编号'] = certNumberField ? certNumberField.description : cert.sequence_number;
        
        // 添加其他字段的内容
        cert.fields.forEach(field => {
          if (field.field_name !== 'cert_number') {  // 排除证书编号字段
            const mapping = allFieldMapping.find(f => f.field_name === field.field_name);
            if (mapping) {
              row[mapping.name] = field.description;
            }
          }
        });
      }
      return row;
    });

    // 确保导出目录存在
    const exportsDir = path.join(process.cwd(), 'uploads', 'exports');
    await fs.mkdir(exportsDir, { recursive: true });
    logger.info('导出目录已确认:', exportsDir);

    // 生成文件路径
    const filePath = path.join(exportsDir, exportFileName);
    const relativeFilePath = path.join('uploads', 'exports', exportFileName);
    
    logger.info('导出文件信息:', {
      format: currentFormat,
      fileName: exportFileName,
      absolutePath: filePath,
      relativePath: relativeFilePath
    });

    // 创建工作簿
    const wb = xlsx.utils.book_new();
    const ws = xlsx.utils.json_to_sheet(exportData, {
      header: ['证书编号', ...allFieldMapping.map(f => f.name)]
    });
    xlsx.utils.book_append_sheet(wb, ws, 'Certificates');

    logger.info('导出格式:', currentFormat);

    // 根据格式保存文件
    if (currentFormat === 'csv') {
      logger.info('使用CSV格式导出');
      const csvContent = xlsx.utils.sheet_to_csv(ws);
      await fs.writeFile(filePath, csvContent, 'utf8');
    } else {
      logger.info('使用XLSX格式导出');
      xlsx.writeFile(wb, filePath);
    }

    logger.info('文件已保存:', {
      absolutePath: filePath,
      relativePath: relativeFilePath,
      format: currentFormat
    });

    // 计算耗时
    const duration = Math.round((Date.now() - startTime.getTime()) / 1000);

    // 更新导出记录状态
    await record.update({
      status: '成功',
      file_path: relativeFilePath,
      file_size: (await fs.stat(filePath)).size,
      duration
    }, { transaction });

    await transaction.commit();
    transaction = null;
    logger.info('事务已提交');

    // 返回文件信息
    res.json({
      code: 200,
      message: '导出成功',
      data: {
        fileName: exportFileName,
        totalCount: certificates.length,
        downloadUrl: `/api/data/download/exports/${exportFileName}`,
        tempFilePath: relativeFilePath
      }
    });
    
  } catch (queryError) {
    logger.error('查询或导出处理失败:', queryError);
    // 回滚事务
    if (transaction) {
      await transaction.rollback();
      logger.info('事务已回滚');
    }
    // 返回统一格式的错误信息
    res.status(400).json({
      code: 400,
      message: '查询或导出处理失败: ' + queryError.message
    });
    return;
  }
};

// 修改下载导出文件的接口
exports.downloadExport = async (req, res) => {
  try {
    const { filename } = req.params;
    const filePath = path.join(process.cwd(), 'uploads', 'exports', filename);
    
    // 检查文件是否存在
    try {
      await fs.access(filePath);
    } catch (error) {
      return res.status(404).json({ message: '文件不存在或已过期' });
    }

    // 获取文件扩展名
    const ext = path.extname(filename).toLowerCase();
    
    // 设置正确的 MIME 类型和文件名编码
    const mimeType = ext === '.csv' 
      ? 'text/csv'
      : 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
    
    res.setHeader('Content-Type', mimeType);
    res.setHeader('Content-Disposition', `attachment; filename*=UTF-8''${encodeURIComponent(filename)}`);
    res.setHeader('Access-Control-Expose-Headers', 'Content-Disposition');
    res.setHeader('Cache-Control', 'no-cache');
    res.setHeader('Pragma', 'no-cache');
    res.setHeader('Expires', '0');

    // 使用原生 fs 模块的 createReadStream
    const fileStream = require('fs').createReadStream(filePath);
    fileStream.pipe(res);

    // 错误处理
    fileStream.on('error', (error) => {
      logger.error('文件流错误:', error);
      if (!res.headersSent) {
        res.status(500).json({ message: '下载失败' });
      }
    });
  } catch (error) {
    logger.error('下载导出文件失败:', error);
    if (!res.headersSent) {
      res.status(500).json({ message: '下载失败' });
    }
  }
};

// 获取记录列表
exports.getRecords = async (req, res) => {
  try {
    const { 
      page = 1, 
      pageSize = 10,
      status,
      type,
      keyword,
      id
    } = req.query;

    // 如果指定了ID，不使用缓存
    if (id) {
      const where = { id };
      const record = await ImportExportRecord.findOne({ where });
      if (!record) {
        return res.status(404).json({ message: '记录不存在' });
      }
      return res.json({
        items: [record],
        total: 1
      });
    }

    // 生成缓存键
    const cacheKey = `${CACHE_KEY.RECORD_LIST}${page}:${pageSize}:${status || ''}:${type || ''}:${keyword || ''}`;
    
    // 尝试从缓存获取
    const cachedData = await redis.get(cacheKey);
    if (cachedData) {
      logger.info('从缓存获取记录列表');
      return res.json(JSON.parse(cachedData));
    }

    const where = {};
    if (type) {
      where.type = type;
    }
    if (status) {
      where.status = status;
    }
    if (keyword) {
      where.file_name = { [Op.like]: `%${keyword}%` };
    }

    const { count, rows } = await ImportExportRecord.findAndCountAll({
      where,
      order: [['created_at', 'DESC']],
      limit: parseInt(pageSize),
      offset: (page - 1) * pageSize
    });

    const result = {
      items: rows,
      total: count
    };

    // 设置缓存
    await redis.set(cacheKey, JSON.stringify(result), 'EX', CACHE_TTL.RECORD_LIST);
    logger.info('记录列表已缓存');

    res.json(result);
  } catch (error) {
    logger.error('获取记录列表失败:', error);
    res.status(500).json({ message: '获取记录失败' });
  }
};

// 批量删除记录
exports.deleteRecords = async (req, res) => {
  try {
    const { ids } = req.body;
    if (!ids || !Array.isArray(ids) || ids.length === 0) {
      return res.status(400).json({ message: '请选择要删除的记录' });
    }

    await ImportExportRecord.destroy({
      where: {
        id: {
          [Op.in]: ids
        }
      }
    });

    // 清除记录列表相关的所有缓存
    const keys = await redis.keys(`${CACHE_KEY.RECORD_LIST}*`);
    if (keys.length > 0) {
      await redis.del(keys);
      logger.info('记录列表缓存已清除');
    }

    res.json({ message: '删除成功' });
  } catch (error) {
    logger.error('删除记录失败:', error);
    res.status(500).json({ message: '删除记录失败' });
  }
};

// 清理临时文件
exports.cleanTempFile = async (req, res) => {
  try {
    const { filePath } = req.body;
    if (!filePath) {
      return res.status(400).json({ message: '文件路径不能为空' });
    }

    // 检查文件是否存在
    try {
      await fs.access(filePath);
    } catch (error) {
      // 文件不存在也返回成功
      return res.json({ message: '文件已清理' });
    }

    // 删除文件
    await fs.unlink(filePath);
    res.json({ message: '文件已清理' });
  } catch (error) {
    logger.error('清理临时文件失败:', error);
    res.status(500).json({ message: '清理文件失败' });
  }
};

// 删除单条记录
exports.deleteRecord = async (req, res) => {
  const t = await sequelize.transaction();
  
  try {
    const { id } = req.params;
    
    // 查找记录
    const record = await ImportExportRecord.findByPk(id);
    if (!record) {
      return res.status(404).json({ message: '记录不存在' });
    }

    logger.info('开始删除记录:', {
      recordId: id,
      type: record.type,
      fileName: record.file_name,
      filePath: record.file_path
    });

    // 如果有文件路径，尝试删除物理文件
    if (record.file_name) {
      const filePath = path.join(process.cwd(), 'uploads', 
        record.type === '导出' ? 'exports' : 'imports',
        record.file_name
      );
      try {
        await fs.access(filePath);
        await fs.unlink(filePath);
        logger.info('成功删除文件:', filePath);
      } catch (error) {
        if (error.code === 'ENOENT') {
          logger.warn('文件已不存在:', filePath);
        } else {
          logger.error('文件删除失败:', {
            filePath,
            error: error.message,
            code: error.code
          });
          await t.rollback();
          return res.status(500).json({ 
            message: `文件删除失败: ${error.message}`,
            code: error.code
          });
        }
      }
    }

    // 删除记录
    await record.destroy({ transaction: t });
    logger.info('记录删除成功:', {
      recordId: id,
      type: record.type
    });
    
    await t.commit();
    res.json({ message: '删除成功' });
  } catch (error) {
    await t.rollback();
    logger.error('删除记录失败:', {
      error: error.message,
      stack: error.stack
    });
    res.status(500).json({ message: '删除失败: ' + error.message });
  }
};

// 下载历史文件
exports.downloadHistoryFile = async (req, res) => {
  try {
    const { id } = req.params;
    
    // 查找记录
    const record = await ImportExportRecord.findByPk(id);
    if (!record) {
      return res.status(404).json({ message: '文件记录不存在' });
    }

    // 检查文件路径是否存在
    if (!record.file_path) {
      logger.error('文件路径不存在:', { recordId: id });
      return res.status(404).json({ message: '文件路径不存在' });
    }

    // 根据记录类型和文件路径构建完整路径
    const filePath = path.join(process.cwd(), record.file_path);
    
    // 检查文件是否存在
    try {
      await fs.access(filePath);
    } catch (error) {
      logger.error('文件不存在:', {
        error,
        recordId: id,
        type: record.type,
        filePath: record.file_path
      });
      return res.status(404).json({ message: '文件不存在或已被删除' });
    }

    // 设置正确的 MIME 类型
    const mimeType = getMimeType(record.file_name);
    
    // 设置响应头
    res.setHeader('Content-Type', mimeType);
    res.setHeader('Content-Disposition', `attachment; filename*=UTF-8''${encodeURIComponent(record.file_name)}`);
    res.setHeader('Access-Control-Expose-Headers', 'Content-Disposition');
    
    // 使用流式传输
    const fileStream = require('fs').createReadStream(filePath);
    
    // 错误处理
    fileStream.on('error', (error) => {
      logger.error('文件流读取错误:', {
        error,
        recordId: id,
        type: record.type,
        filePath: record.file_path
      });
      if (!res.headersSent) {
        res.status(500).json({ message: '文件下载失败' });
      }
    });

    // 等待流完成
    await new Promise((resolve, reject) => {
      fileStream.pipe(res);
      fileStream.on('end', () => {
        logger.info('文件下载完成:', {
          recordId: id,
          type: record.type,
          fileName: record.file_name,
          fileSize: record.file_size
        });
        resolve();
      });
      fileStream.on('error', reject);
      res.on('error', reject);
    });
  } catch (error) {
    logger.error('下载历史文件失败:', {
      error,
      recordId: req.params.id
    });
    if (!res.headersSent) {
      res.status(500).json({ message: '下载失败: ' + error.message });
    }
  }
};

// 清理过期日志文件
const cleanExpiredRecords = async (retentionDays) => {
  const t = await sequelize.transaction();
  
  try {
    // 计算截止日期
    const cutoffDate = new Date();
    cutoffDate.setDate(cutoffDate.getDate() - retentionDays);
    
    logger.info('开始清理过期日志:', {
      retentionDays,
      cutoffDate
    });

    // 查找过期记录
    const expiredRecords = await ImportExportRecord.findAll({
      where: {
        created_at: {
          [Op.lt]: cutoffDate
        }
      },
      transaction: t
    });

    if (!expiredRecords.length) {
      await t.commit();
      return { success: true, message: '没有过期记录需要清理' };
    }

    logger.info('找到过期记录:', {
      count: expiredRecords.length,
      oldestRecord: expiredRecords[0].created_at
    });

    const results = {
      success: [],
      failed: []
    };

    // 删除过期文件
    for (const record of expiredRecords) {
      if (!record.file_name) {
        results.success.push(record.id);
        continue;
      }

      const filePath = path.join(process.cwd(),
        record.type === '导出' ? 'exports' : 'imports',
        record.file_name
      );
      try {
        await fs.access(filePath);
        await fs.unlink(filePath);
        logger.info('成功删除过期文件:', {
          recordId: record.id,
          filePath
        });
        results.success.push(record.id);
      } catch (error) {
        if (error.code === 'ENOENT') {
          logger.warn('过期文件已不存在:', {
            recordId: record.id,
            filePath
          });
          results.success.push(record.id);
        } else {
          logger.error('过期文件删除失败:', {
            recordId: record.id,
            filePath,
            error: error.message
          });
          results.failed.push({
            id: record.id,
            error: error.message
          });
        }
      }
    }

    // 删除成功的记录
    if (results.success.length > 0) {
      await ImportExportRecord.destroy({
        where: { id: results.success },
        transaction: t
      });
    }

    await t.commit();
    return {
      success: true,
      message: `清理完成：成功 ${results.success.length} 条，失败 ${results.failed.length} 条`,
      details: results
    };
  } catch (error) {
    await t.rollback();
    logger.error('清理过期记录失败:', error);
    return {
      success: false,
      message: '清理过期记录失败: ' + error.message
    };
  }
};

// 获取日志保留天数
const getRetentionDays = async () => {
  try {
    const [result] = await sequelize.query(
      'SELECT value FROM settings WHERE `key` = ?',
      {
        replacements: ['log_retention_days']
      }
    );
    return result.length > 0 ? parseInt(result[0].value) : 30; // 默认30天
  } catch (error) {
    logger.error('获取日志保留天数失败:', error);
    return 30; // 出错时使用默认值
  }
};

// 自动清理过期日志
const autoCleanExpiredRecords = async () => {
  try {
    const retentionDays = await getRetentionDays();
    logger.info('开始自动清理过期日志:', { retentionDays });
    return await cleanExpiredRecords(retentionDays);
  } catch (error) {
    logger.error('自动清理过期日志失败:', error);
    return {
      success: false,
      message: '自动清理失败: ' + error.message
    };
  }
};

// 每天凌晨2点执行清理
setInterval(async () => {
  const now = new Date();
  if (now.getHours() === 2 && now.getMinutes() === 0) {
    logger.info('执行定时清理任务');
    await autoCleanExpiredRecords();
  }
}, 60 * 1000); // 每分钟检查一次

// 修改设置日志保留天数的方法
exports.setRetentionDays = async (req, res) => {
  try {
    const { days } = req.body;
    
    // 验证天数范围
    const retentionDays = parseInt(days);
    if (isNaN(retentionDays) || retentionDays < 0 || retentionDays > 3650) {
      return res.status(400).json({ 
        message: '保留天数必须在0-3650天之间' 
      });
    }

    // 保存设置
    await sequelize.query(
      'INSERT INTO settings (`key`, value, created_at, updated_at) VALUES (?, ?, NOW(), NOW()) ON DUPLICATE KEY UPDATE value = ?, updated_at = NOW()',
      {
        replacements: ['log_retention_days', retentionDays.toString(), retentionDays.toString()]
      }
    );

    // 立即执行一次清理
    const result = await cleanExpiredRecords(retentionDays);
    
    res.json({
      message: '设置成功',
      retentionDays,
      cleanupResult: result
    });
  } catch (error) {
    logger.error('设置日志保留天数失败:', error);
    res.status(500).json({ 
      message: '设置失败: ' + error.message 
    });
  }
};

// 获取日志保留天数设置
exports.getRetentionDays = async (req, res) => {
  try {
    const days = await getRetentionDays();
    res.json({
      retentionDays: days,
      min: 0,
      max: 3650,
      default: 30
    });
  } catch (error) {
    logger.error('获取日志保留天数失败:', error);
    res.status(500).json({ 
      message: '获取设置失败: ' + error.message 
    });
  }
};

// 下载导入文件
exports.downloadImport = async (req, res) => {
  try {
    const { filename } = req.params;
    const filePath = path.join(process.cwd(), 'uploads', 'imports', filename);
    
    // 检查文件是否存在
    try {
      await fs.access(filePath);
    } catch (error) {
      return res.status(404).json({ message: '文件不存在或已过期' });
    }

    // 获取文件扩展名
    const ext = path.extname(filename).toLowerCase();
    
    // 设置正确的 MIME 类型和文件名编码
    const mimeType = ext === '.csv' 
      ? 'text/csv'
      : 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
    
    res.setHeader('Content-Type', mimeType);
    res.setHeader('Content-Disposition', `attachment; filename*=UTF-8''${encodeURIComponent(filename)}`);
    res.setHeader('Access-Control-Expose-Headers', 'Content-Disposition');
    res.setHeader('Cache-Control', 'no-cache');
    res.setHeader('Pragma', 'no-cache');
    res.setHeader('Expires', '0');

    // 使用原生 fs 模块的 createReadStream
    const fileStream = require('fs').createReadStream(filePath);
    fileStream.pipe(res);

    // 错误处理
    fileStream.on('error', (error) => {
      logger.error('文件流错误:', error);
      if (!res.headersSent) {
        res.status(500).json({ message: '下载失败' });
      }
    });
  } catch (error) {
    logger.error('下载导入文件失败:', error);
    if (!res.headersSent) {
      res.status(500).json({ message: '下载失败' });
    }
  }
};

// 清理临时文件
exports.cleanTempFile = async (req, res) => {
  try {
    const { filePath } = req.body;
    if (!filePath) {
      return res.status(400).json({ message: '文件路径不能为空' });
    }

    // 检查文件是否存在
    try {
      await fs.access(filePath);
    } catch (error) {
      // 文件不存在也返回成功
      return res.json({ message: '文件已清理' });
    }

    // 删除文件
    await fs.unlink(filePath);
    res.json({ message: '文件已清理' });
  } catch (error) {
    logger.error('清理临时文件失败:', error);
    res.status(500).json({ message: '清理文件失败' });
  }
}; 